/*
 * Copyright (C) 2009 Leandro Aparecido <lehphyro@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.metalframework.samples.petclinic;

import java.util.*;

import javax.persistence.*;
import javax.validation.*;
import javax.validation.constraints.*;

import org.codehaus.jackson.annotate.*;
import org.metalframework.annotation.*;
import org.metalframework.persistence.annotation.*;
import org.metalframework.samples.petclinic.annotation.*;
import org.metalframework.validation.constraints.*;
import org.springframework.transaction.annotation.*;

@Transactional
@PetClinicComponent
@Entity
public class Pet extends IdentifiedEntity {

	private static final long serialVersionUID = -2572837440661558521L;

	private String name;
	
	private Date birthDate;
	
	private Type type;
	
	private Owner owner;
	
	private List<Visit> visits;
	
	public Pet() {
		this(null, null, null);
	}
	
	public Pet(String name, Date birthDate, Type type) {
		setName(name);
		setBirthDate(birthDate);
		setType(type);
		
		visits = new ArrayList<Visit>();
	}
	
	public Visit takeToVeterinary(int year, int month, int day, String description) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(year, month, day);
		
		return takeToVeterinary(calendar.getTime(), description);
	}
	
	public Visit takeToVeterinary(Date date, String description) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		
		Visit visit = new Visit(calendar.getTime(), description, this);
		takeToVeterinary(visit);
		
		return visit;
	}
	
	@AutomaticPersistence
	@Navigation(view = "/owner.xhtml?id=#{ownerId}", redirect = true)
	public void takeToVeterinary(@Validate Visit visit) {
		visit.setPet(this);
		visits.add(visit);
	}
	
	@NotNull @NotBlank
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	@NotNull @Past
	@Temporal(TemporalType.DATE)
	public Date getBirthDate() {
		return birthDate;
	}

	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}

	@NotNull
	@Enumerated(EnumType.STRING)
	public Type getType() {
		return type;
	}

	public void setType(Type type) {
		this.type = type;
	}

	@ManyToOne
	@JsonIgnore
	public Owner getOwner() {
		return owner;
	}

	public void setOwner(Owner owner) {
		this.owner = owner;
	}

	@Valid
	@org.hibernate.annotations.Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) 
	@OneToMany(mappedBy = "pet", cascade = { CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.EAGER)
	@OrderBy("date DESC")
	public List<Visit> getVisits() {
		return visits;
	}

	public void setVisits(List<Visit> visits) {
		this.visits = visits;
	}
	
	@Override
	public String toString() {
		return super.toString() + ";name=" + getName() + ";birthDate=" + getBirthDate() + ";type=" + getType();
	}
	
	public static enum Type {
		DOG("dog"),
		CAT("cat"),
		HAMSTER("hamster"),
		LIZARD("lizard"),
		SNAKE("snake"),
		BIRD("bird"),
		;
		
		private String name;
		
		private Type(String name) {
			this.name = name;
		}
		
		public String getName() {
			return name;
		}
		
		@Override
		public String toString() {
			return getName();
		}
	}
}
